package com.bert.controller;

import com.bert.client.GrpcClientService;
import com.bert.entity.PerformanceEntity;
import com.bert.feign.TestClient;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("/performance")
public class PerformanceController {

    @Resource
    private TestClient testClient;
    @Resource
    private GrpcClientService grpcClientService;

    @GetMapping("/all")
    public List<PerformanceEntity> all(@RequestParam long number) {
        PerformanceEntity gRPC = this.gRPC(number);
        PerformanceEntity http = this.http(number);
        PerformanceEntity local = this.local(number);
        return Arrays.asList(gRPC, http, local);
    }

    @GetMapping("/gRPC")
    public PerformanceEntity gRPC(@RequestParam long number) {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < number; i++) {
            this.grpcClientService.sendMessage("test");
        }
        long endTime = System.currentTimeMillis();
        return this.getTime("gRPC", number, startTime, endTime);
    }

    @GetMapping("/http")
    public PerformanceEntity http(@RequestParam long number) {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < number; i++) {
            testClient.path("test");
        }
        long endTime = System.currentTimeMillis();
        return this.getTime("HTTP", number, startTime, endTime);
    }

    @GetMapping("/local")
    public PerformanceEntity local(@RequestParam long number) {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < number; i++) {
            this.getString("test");
        }
        long endTime = System.currentTimeMillis();
        return this.getTime("本地方法", number, startTime, endTime);
    }

    private String getString(String test){
        long startTime = System.currentTimeMillis();
        long endTime = System.currentTimeMillis();
        long all = endTime - startTime;
        return test + all;
    }

    private PerformanceEntity getTime(String name, long number, long startTime, long endTime){
        long totalTime = endTime - startTime;
        BigDecimal averageTime = this.getNumber(2, totalTime, number);
        BigDecimal tps = this.getNumber(0, number * 1000, totalTime);
        return PerformanceEntity.builder()
                .project(name + "循环调用 "+ number +"次")
                .totalTime(totalTime + " ms")
                .averageTime(averageTime + " ms")
                .TPS(tps + " r/s")
                .build();
    }

    private BigDecimal getNumber(int n, long a, long b){
        if (b == 0L) {
            b = 1L;
        }
        return BigDecimal.valueOf(a).divide(BigDecimal.valueOf(b), n, RoundingMode.HALF_UP);
    }

}
